package com.vcs.web;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.InputStream;
import java.util.List;
import java.util.Map;

import jxl.Workbook;
import jxl.format.Colour;
import jxl.format.UnderlineStyle;
import jxl.write.Label;
import jxl.write.Number;
import jxl.write.NumberFormats;
import jxl.write.WritableCellFormat;
import jxl.write.WritableFont;
import jxl.write.WritableSheet;
import jxl.write.WritableWorkbook;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.struts2.ServletActionContext;
import org.apache.struts2.interceptor.ParameterAware;
import org.apache.struts2.interceptor.RequestAware;
import org.apache.struts2.interceptor.SessionAware;

import com.opensymphony.xwork2.ActionContext;
import com.opensymphony.xwork2.ActionSupport;
import com.opensymphony.xwork2.ModelDriven;
import com.vcs.dao.JobseekerDAO;
import com.vcs.dao.JobseekerDAOImpl;
import com.vcs.dao.UtilDAO;
import com.vcs.dao.UtilDAOImpl;
import com.vcs.domain.Client;
import com.vcs.domain.Job;
import com.vcs.domain.JobApplication;
import com.vcs.domain.Jobseeker;
import com.vcs.util.MailUtilRunnable;
import com.vcs.util.Util;
import com.vcs.util.VcsConstants;

@SuppressWarnings("serial")
public class JobseekerAction extends ActionSupport implements
		ModelDriven<Jobseeker>, SessionAware, RequestAware, ParameterAware {

	Log log = LogFactory.getLog(JobseekerAction.class);
	private Map<String, Object> sessionMap;
	private Map<String, Object> requestMap;
	private Map<String, String[]> parameterMap;
	Jobseeker jobseeker = new Jobseeker();
	JobseekerDAO jobseekerDao = new JobseekerDAOImpl();
	UtilDAO udao = new UtilDAOImpl();
	
	private InputStream inputStream = null;

	public InputStream getInputStream() {
		return inputStream;
	}

	public void setInputStream(InputStream inputStream) {
		this.inputStream = inputStream;
	}

	@Override
	public Jobseeker getModel() {
		return jobseeker;
	}

	@Override
	public void setSession(Map<String, Object> sessionMap) {
		this.sessionMap = sessionMap;
	}

	@Override
	public void setRequest(Map<String, Object> requestMap) {
		this.requestMap = requestMap;
	}

	// TODO ADD GET REQUEST METHOD
	public Map<String, Object> getRequest() {
		return this.requestMap;
	}

	@Override
	public void setParameters(Map<String, String[]> parameterMap) {
		this.parameterMap = parameterMap;

	}

	public Map<String, String[]> getParameterMap() {
		return parameterMap;
	}

	public String verifyJobseeker() {

		log.info("verifyJobseeker()...");
		String username = jobseeker.getUsername();
		String password = jobseeker.getPassword();
		log.info("USERNAME:" + username + " PASSWORD: " + password);
		Jobseeker jobseekerProfile = jobseekerDao.getProfileByUsername(
				username, password);
		if (jobseekerProfile != null) {
			new ClientAction().logout();
			sessionMap.put("js", jobseekerProfile);
			log.info("Jobseeker's profile set in SESSION successfully. variable name is 'js'");
			return SUCCESS;
		} else {
			// log.info("inside else, returning INPUT");
			addActionError("Invalid User Name or Password");
			// log.info("Leaving verifyJobseeker() method");
			return INPUT;
		}
	}

	/**
	 * Calls Dao layers's save method to save jobseeker object into database.
	 * 
	 * @return
	 */
	public String save() {
		// Check for a valid session
		if(sessionMap == null){
			log.debug("Session was null");
		}
		log.debug("Session : "+ sessionMap);
		log.info("jobseeker Before saving: " + jobseeker);
		validateJobseeker();
		if (hasFieldErrors()) {
			return INPUT;
		}
		jobseeker.setProfileCreationDate(new java.util.Date());
		jobseekerDao.save(jobseeker);

		// prepare and send an email to the candidate just to congratulate him.
		String mBody = "Congratulations  "
				+ jobseeker.getFirstName()
				+ "\n\nYour Account has been created on http://vowconsultancy.com with following details:\n\n"
				+ "User Name: "
				+ jobseeker.getUsername()
				+ "\nPassword: "
				+ jobseeker.getPassword()
				+ "\n\nPlease click on the following link to Login\n"
				+ "http://vowconsultancy.com/js/profile.action\n\n"
				+ "You will need to upload your latest resume after logging in.\n"
				+ "This will help the VCS team to find opportunities matching to your career interests.\n\n"
				+ "To know more about Vow Consultancy Services please visit http://vowconsultancy.com/aboutus.action \n\n"
				+ "You can find our contact information on http://vowconsultancy.com/contactus.action"
				+ "\n\nWarm Regards,\nTeam VCS";

		Thread t = new Thread(
				new MailUtilRunnable(
						getText("vcsEmailId"),
						jobseeker.getEmail(),
						"",
						"Congratulations Your account created on http://vowconsultancy.com",
						mBody));
		t.start();

		return SUCCESS;
	}

	public String update() {
		log.info("update()...");
		// if session has expired send user to home jobseeker login page
		if(sessionMap.get("js") ==  null){
			return ERROR;
		}
		// update jobseeker - take values from session.
		jobseeker.setJobseekerId(((Jobseeker) sessionMap.get("js"))
				.getJobseekerId());
		jobseeker.setUsername(((Jobseeker) sessionMap.get("js")).getUsername());
		jobseeker.setPassword(((Jobseeker) sessionMap.get("js")).getPassword());
		jobseeker.setResumeName(((Jobseeker) sessionMap.get("js"))
				.getResumeName());
		log.debug("Jobseeker object before saving: " + jobseeker);
		jobseekerDao.update(jobseeker);
		// now update jobseeker object stored in session
		sessionMap.remove("js");
		sessionMap.put("js", jobseeker);
		return SUCCESS;
	}

	@SuppressWarnings("rawtypes")
	public String applyJob() {
		log.info("applyJob()...");
		Long jobId = null;
		Map parameters = ActionContext.getContext().getParameters();
		log.info("parameters: " + parameters);
		log.info("parameters.get('jobId'): " + parameters.get("jobId"));
		String[] a = (String[]) parameters.get("jobId");
		log.info("a: " + a);

		jobId = Long.parseLong(a[0]);
		Jobseeker js = (Jobseeker) sessionMap.get("js");

		// prepare jobApplication object
		JobApplication jobApplication = new JobApplication();
		jobApplication.setJobId(jobId);
		jobApplication.setJobseekerId(js.getJobseekerId());
		jobApplication.setAppliedOnDate(new java.util.Date());
		log.info("jobApplication: " + jobApplication);
		// fetch list of jobs applied by candidate and check if he has alreay
		// applied for the current job, if yes then don't make a new database
		// entry for this job
		List<Job> appliedJobList = jobseekerDao.getJobAppliedByMe(js
				.getJobseekerId());

		// log.info("Job id " + jobId);
		if (appliedJobList != null && appliedJobList.size() > 0) {
			for (Job j : appliedJobList) {
				// log.info("^^^^^^^^^^^ j " + j.getJobId());
				int result = j.getJobId().compareTo(jobId);
				if (result == 0) {
					log.info("Candidate has already applied for this job");
					return SUCCESS;
				}
			}
		}
		// call DAO method and pass jobApplication object
		jobseekerDao.applyJob(jobApplication);
		return SUCCESS;
	}

	public String getJobsAppliedByMe() {
		// TODO get job applied by candidate
		log.info("getJobsAppliedByMe()...");
		Jobseeker js = (Jobseeker) sessionMap.get("js");
		Long jobseekerId = null;
		if (js == null) {
			log.info("Jobseeker obtained from session is NULL");
		} else {
			jobseekerId = js.getJobseekerId();
			log.info("Current Logged in Jobseeker's id is:  " + jobseekerId);
		}
		List<Job> jobList = jobseekerDao.getJobAppliedByMe(jobseekerId);
		requestMap.put("jobList", jobList);
		return SUCCESS;
	}

	/**
	 * This method handles the profile popup, admin clicks on the view candidate
	 * profile link on the applied jobs page.
	 * 
	 * @return
	 */
	public String getProfileById() {
		log.info("getProfileById()...");
		String[] params = (String[]) parameterMap.get("cid");
		Long jobseekerId = null;
		Jobseeker js = null;
		log.info("--> " + params);
		if (params != null) {
			log.info("Parameters length " + params.length);

			for (String s : params) {
				log.info(s);
				if (s != null) {
					jobseekerId = Long.parseLong(s);
				}
			}
			log.info("jobseeker's id comming from jsp ==> " + jobseekerId);

			js = jobseekerDao.getProfileById(jobseekerId);
		}
		log.info("js --> " + js);
		requestMap.put("js", js);
		return SUCCESS;
	}

	// public String getRequest

	/**
	 * Generates a downloadable excel sheet with the Entire Candidate database
	 * Supposed to be called by admin only.
	 */
	public String dbExcelDownload() {
		log.info("dbExcelDownload()...");
		Client client = (Client) sessionMap.get("client");
		if (client != null && client.getRole().equals(VcsConstants.ADMIN)) {

			// Call dao method to get the list of all jobseekers
			List<Jobseeker> jobseekersList = jobseekerDao.listJobseeker();
			// System.setProperty("user.dir", File.separator );
			try {
				// 1. Create a writeable workbook
				WritableWorkbook workbook = Workbook.createWorkbook(new File(
						"vcs_db.xls"));

				// 2. Create a writable sheet
				WritableSheet sheet = workbook.createSheet("vcs database", 0);
				// 3. Add column headers to the sheet.
				WritableCellFormat headerFormat = new WritableCellFormat();
				headerFormat.setBackground(Colour.CORAL);
				WritableFont times14ptBoldUnderline = new WritableFont(
						WritableFont.TIMES, 12, WritableFont.BOLD, false,
						UnderlineStyle.NO_UNDERLINE);
				headerFormat.setFont(times14ptBoldUnderline);

				String[] colHeaders = { "CANDIDATE ID", "CANDIDATE NAME",
						"GENDER", "EMAIL", "CELL NUMBER", "CURRENT LOCATION",
						"PREFERRED LOCATION", "CURRENT EMPLOYER",
						"PREVIOUS EMPLOYER", "DESIGNATION", "KEY SKILLS",
						"TOTAL EXPERIENCE", "HIGHEST QUALIFICATION",
						"YEAR OF PASSING", "SPECIALIZATION",
						"COLLEGE//INSTITUTE", "USERNAME ON VCS",
						"RESUME FILE NAME" };

				for (int i = 0; i < colHeaders.length; i++) {
					System.out.println(i);
					Label headerLbl = new Label(i, 0, colHeaders[i],
							headerFormat);
					sheet.addCell(headerLbl);
				}
				// 4. Write data to the sheet.
				int row = 1;
				for (Jobseeker js : jobseekersList) {
					int col = 0;
					// System.out.println(js);

					// col 1 - jobseeker id
					WritableCellFormat integerFormat = new WritableCellFormat(
							NumberFormats.INTEGER);
					jxl.write.Number jobseekerId = new jxl.write.Number(col,
							row, js.getJobseekerId(), integerFormat);
					sheet.addCell(jobseekerId);
					// col 2 - add name
					Label name = new Label(col + 1, row, js.getFirstName()
							+ " " + js.getLastName());
					sheet.addCell(name);
					// col 3 - gender
					Label gender = null;
					if (js.isGender()) {
						gender = new Label(col + 2, row, "Male");
					} else {
						gender = new Label(col + 2, row, "Female");
					}
					sheet.addCell(gender);
					// col 3 - email
					Label email = new Label(col + 3, row, js.getEmail());
					sheet.addCell(email);
					// col 4 - Cell number
					jxl.write.Number cellNumber = new jxl.write.Number(col + 4,
							row, js.getMobileNumber(), integerFormat);
					sheet.addCell(cellNumber);
					// col 5 - current Location

					String cloc = udao.getLocationById(js.getCurrentLocation());
					Label curLoc = new Label(col + 5, row, cloc);
					sheet.addCell(curLoc);
					// col 5 - preferred Location
					Label prefLoc = new Label(col + 6, row,
							udao.getLocationById(js.getPreferredLocation()));
					sheet.addCell(prefLoc);
					// col 4 - current employer
					Label curEmployer = new Label(col + 7, row,
							js.getCurrentEmployer());
					sheet.addCell(curEmployer);
					// col 5 - previous employer
					Label prevEmployer = new Label(col + 8, row,
							js.getPreviousEmployer());
					sheet.addCell(prevEmployer);
					// col 6 - Designation
					Label designation = new Label(col + 9, row,
							js.getDesignation());
					sheet.addCell(designation);
					// col 7 - key Skills
					Label keySkills = new Label(col + 10, row,
							js.getKeySkills());
					sheet.addCell(keySkills);
					// col 8 - Experience
					WritableCellFormat floatFormat = new WritableCellFormat(
							NumberFormats.FLOAT);
					jxl.write.Number experience = new jxl.write.Number(
							col + 11, row, Float.parseFloat(js.getExpYears()
									+ "." + js.getExpMonths()), floatFormat);
					sheet.addCell(experience);
					// col 12 - highest qualification
					Label highestQualification = new Label(col + 12, row,
							udao.getQualificationById(js
									.getHighestQualification()));
					sheet.addCell(highestQualification);
					// col 13 year of passing
					jxl.write.Number yop = new Number(col + 13, row,
							js.getYearOfPassing(), integerFormat);
					sheet.addCell(yop);
					// col 14 - specialization
					Label specialization = new Label(col + 14, row,
							js.getSpecialization());
					sheet.addCell(specialization);
					// col 15 college/ institute
					Label institute = new Label(col + 15, row,
							js.getInstitute());
					sheet.addCell(institute);
					// col 16 - username
					Label uname = new Label(col + 16, row, js.getUsername());
					sheet.addCell(uname);
					// COL 17 - resume file name
					Label resumeName = new Label(col + 17, row,
							js.getResumeName());
					sheet.addCell(resumeName);

					row++;
				}

				workbook.write();
				workbook.close();
				System.out.println("Current Diretory is:"
						+ System.getProperty("user.dir"));

			} catch (Exception e) {
				e.printStackTrace();
			}
		}

		// Prepare for download

		ServletActionContext.getResponse().setHeader("Content-Disposition",
				"attachment; filename=\"" + "vcs_db.xls" + "\"");

		String opSys = System.getProperty("os.name"); // find OS
		log.info("Operating system is: [" + opSys + "]");

		String fullFileName = null;
		String workingDir = "";

		if (opSys.equalsIgnoreCase("Linux")) {

			fullFileName = "." + workingDir + File.separator + "vcs_db.xls";
		} else {
			fullFileName = workingDir + File.separator + "vcs_db.xls";
		}

		log.info("Full file path of excel is : [" + fullFileName + "]");

		try {
			inputStream = new FileInputStream(new File(fullFileName));
		} catch (FileNotFoundException fnf) {
			log.info("-----------Database EXCEL not available for download ------------");
		}

		return SUCCESS;
	}

	/**
	 * This method sends a password recovery email with Username and password.
	 * Takes an email id as input from request parameters
	 * 
	 * @return SUCCESS when mail sent successfully.
	 */

	public String sendPassRecoveryMail() {
		log.debug("sendPassRecoveryMail()...");
		//mdao.getPublicProfileKeywords();
		
		String email = null;
		String status = null;

		email = getParameterMap().get("email")[0];
		email = email.trim();
		
		status = getParameterMap().get("status")[0];
		log.info(" >>>>>>>>>>>>>>>>>>>>>>> email >" + email + "<");

		if (email == null || email == "") {
			addFieldError("email", "Please enter your email id   ");
			return SUCCESS;
		} else {
			if (!Util.isValidEmailAddress(email)) {
				addFieldError("email", "Invalid email id   ");
				return SUCCESS;
			}
		}

		// log.info("----------> " + status);

		// Fetch all email ids from database and check whether this id is
		// present in database
		List<String> allEmailIds = jobseekerDao.getAllEmailIds();

		if (allEmailIds.contains(email)) {
			requestMap.put("status", "found");
			log.info("mail id found in database");
		} else {
			addFieldError("email", "Your Email id is not registered with us  ");
			return SUCCESS;
		}

		// TODO fetch User name and password by passing email id

		String[] credentials = jobseekerDao.getUsernameAndPassword(email);

		// TODO Sending mail logic

		String mailBody = getText("email.js.pass.recovery.body.before")
				+ "\nUser Name: " + credentials[0] + "\nPassword: "
				+ credentials[1] +"\n"
				+getText("email.js.pass.recovery.body.after");

		MailUtilRunnable mailUtilRunnable = new MailUtilRunnable(
				getText("email.js.pass.recovery.from"), email,
				getText("email.js.pass.recovery.bcc"),
				getText("email.js.pass.recovery.subject"), mailBody);
		
		Thread t = new Thread(mailUtilRunnable);
		t.start();
		log.info("Mail With username and password sent to " + email);
		return SUCCESS;
	}

	/**
	 * Validates a jobseeker's registration form
	 */

	private void validateJobseeker() {
		// TODO Jobseeker's registration form to be validated.

		// username
		String uname = jobseeker.getUsername();
		if (uname.contains(" ")) {
			addFieldError("username", "User Name should not contain spaces");
		} else if (uname == null || uname.length() < 5 || uname.length() > 15) {
			addFieldError("username",
					"User Name should be between 5 to 15 characters long");
		} else {
			List<String> allUsernames = jobseekerDao.getAllUsernames();
			if (allUsernames.contains(jobseeker.getUsername())) {
				log.info("Username is already registerd.");
				addFieldError("username",
						"User Name already registerd, Please enter a different User Name");
			}
		}

		// Password
		if (jobseeker.getPassword().length() == 0) {
			addFieldError("password", "Please enter Password");
		} else if (jobseeker.getPassword().length() < 5
				|| jobseeker.getPassword().length() > 15) {
			addFieldError("password",
					"Password should be between 5 to 15 characters long");
		}

		// EMAIL
		if (!Util.isValidEmailAddress(jobseeker.getEmail())) {
			addFieldError("email", "Please enter your valid email id");
		}

		// FIRST NAME
		if (jobseeker.getFirstName().length() > 120) {
			addFieldError("firstName", "First Name is too long");
		} else if (jobseeker.getFirstName().equals("")
				|| jobseeker.getFirstName() == null) {
			addFieldError("firstName", "Please enter First Name");
		}
		// LAST NAME
		if (jobseeker.getLastName().length() > 120) {
			addFieldError("lastName", "Last Name is too long");
		} else if (jobseeker.getLastName().equals("")
				|| jobseeker.getLastName() == null) {
			addFieldError("lastName", "Please enter Last Name");
		}
		// MOBILE NUMBER
		if (jobseeker.getMobileNumber() < 1000000000L
				|| jobseeker.getMobileNumber() > 9999999999L) {
			addFieldError(
					"mobileNumber",
					"Incorrect length! Mobile number should be a 10 digit number without country code.");
		}
		// CURRENT EMPLOYER
		/*
		 * if(jobseeker.getCurrentEmployer().length() == 0){
		 * addFieldError("currentEmployer",
		 * "Please enter your Current Employer"); }
		 */

		// DESIGNATION
		if (jobseeker.getDesignation().length() == 0) {
			addFieldError("designation",
					"Please enter Designation of your current job");
		}

		// KEY SKILLS
		if (jobseeker.getKeySkills().length() < 2) {
			addFieldError("keySkills", "Please enter Your Skills");
		}
		// INSTITUTE
		if (jobseeker.getInstitute().length() < 2) {
			addFieldError("institute",
					"Please enter name of Educational Institute you last attended");
		}
	}
}
